package com.yihen.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.yihen.dto.*;
import com.yihen.mappers.GoodsMapper;
import com.yihen.mappers.OrderMapper;
import com.yihen.pojo.Order;
import com.yihen.util.LevelCheck;
import com.yihen.vo.OrderVO;
import com.yihen.vo.UserVO;
import com.yihen.mappers.UserMapper;
import com.yihen.pojo.User;
import com.yihen.service.UserService;
import com.yihen.util.IdWorker;
import com.yihen.util.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import java.util.*;
import java.util.concurrent.*;

import static com.yihen.util.Constants.LOGIN_USER_KEY;
import static com.yihen.util.Constants.LOGIN_USER_TTL;
@Service
@Slf4j
public class IUserService implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private GoodsMapper goodsMapper;
    @Resource
    private OrderMapper orderMapper;


    // 阻塞队列
    private BlockingQueue<Long> userTasks = new ArrayBlockingQueue<>(1024 * 1024);

    // 线程池
    private static final ExecutorService USER_EXECUTOR = Executors.newSingleThreadExecutor();

    @PostConstruct
    private void init() {
        USER_EXECUTOR.submit(new UserHandler());
    }
    private class UserHandler implements Runnable{
        @Override
        public void run() {
            while (true) {
                try {
                    Long userId = userTasks.take();
                    goodsMapper.deleteGoodsByUserId(userId);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        }
    }





    @Override
    public Result login(String phone, String password) {
        User user = userMapper.queryUserByPhone(phone);
        if (user == null) {
            return new Result("用户不存在");
        }
        // 验证登陆
        if (DigestUtil.md5Hex(password).equals(user.getPassword())) {
            // TODO 是否已经登陆
            String s = stringRedisTemplate.opsForValue().get("user:" +user.getUserId().toString());
            if (s != null) {
                // 已经登陆过了
                return new Result("用户已经登陆!");
            }
            // 验证成功
            // 随机生成token
            String token = UUID.randomUUID().toString(true);
            // 复制对象属性
            UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            // 存储基本信息
            stringRedisTemplate.opsForValue().set("user:"+userDTO.getUserId(), JSONUtil.toJsonStr(userDTO));
            stringRedisTemplate.opsForValue().set("user_root:"+userVO.getUserId(), JSONUtil.toJsonStr(userVO));

            //  将User对象转换为HashMapper存储
            Map<String, Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(),
                    CopyOptions.create().setIgnoreNullValue(true).
                            setFieldValueEditor((fieldName,fieldValue)->fieldValue.toString()));
            //  存储token
            stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY+token,userMap);
            //  设置token的有效期
            stringRedisTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_TTL, TimeUnit.MINUTES);
            // 设置基本信息有效期
            stringRedisTemplate.expire("user:"+userDTO.getUserId(), LOGIN_USER_TTL, TimeUnit.MINUTES);
            stringRedisTemplate.expire("user_root:"+userVO.getUserId(), LOGIN_USER_TTL, TimeUnit.MINUTES);
            LoginDTO loginDTO = new LoginDTO(userDTO.getUserId(),token);
            log.info("用户:{} 登陆成功",user.getUserId().toString());

            return new Result(true, loginDTO,"登陆成功！");
        } else return new Result("密码错误");

    }

    @Override
    public Result logout() {
        UserVO user = UserHolder.getUser();
        String id = user.getUserId().toString();
        // 移除redis
        stringRedisTemplate.delete("user:" + id);
        stringRedisTemplate.delete("user_root:" + id);
        log.info("用户:{} 退出登陆",id);
        return new Result(true, "退出成功!");
    }

    @Override
    public Result getInformation() {
        Long id = UserHolder.getUser().getUserId();
        User user = getById(id);
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        return new Result(true, userDTO);
    }

    @Override
    public Result updatePassword(String password, String newpassword) {
        Long id = UserHolder.getUser().getUserId();
        User user = getById(id);
        String  oldpassword= DigestUtil.md5Hex(password);
        if (!user.getPassword().equals(oldpassword)) {
            return new Result("原密码错误!");
        }
        String s = DigestUtil.md5Hex(newpassword);
        userMapper.updatePassword(id, s);
        log.info("用户:{} 修改密码成功",UserHolder.getUser().getUserId().toString());

        return new Result(true, "修改成功!");
    }

    @Override
    public Result getAllUser() {
        Result result = LevelCheck.levelIsOK(2, "无法查看用户信息!");
        if (!result.isFlag()) {
            return result;
        }

        List<User> users = userMapper.queryUser();

        return new Result(true, users);
    }

    @Override
    public Result addUser(User user) {
        Result result = LevelCheck.levelIsOK(2, "无法添加用户!");
        if (!result.isFlag()) {
            return result;
        }
        Long userId = IdWorker.getId();
        user.setUserId(userId);
        user.setLevel(1);
        user.setPassword(DigestUtil.md5Hex(user.getPassword()));
        try {
            int i = userMapper.inertUser(user);
            log.info("用户:{} 添加用户成功",UserHolder.getUser().getUserId().toString());

            return new Result(true,"添加成功!");
        } catch (Exception e) {
             return new Result("添加失败,邮箱或手机号已被注册!");
        }

    }

    @Override
    public Result updateUserLevel(int level, Long userId) {

        Result result = LevelCheck.levelIsOK(3, "无法修改用户权限!");
        if (!result.isFlag()) {
            return result;
        }

        int i = userMapper.updateUserLevel(level, userId);
        if (i==0) return new Result("请输入正确的ID!");
        log.info("用户:{} 修改用户权限成功",UserHolder.getUser().getUserId().toString());

        return new Result(true, "修改成功!");

    }

    @Override
    public Result selectUserByCondition(int mode, String condition) {
        Result result = LevelCheck.levelIsOK(2, "无法查询用户!");
        if (!result.isFlag() && mode != 3) {
            return result;
        }
        User user=null;
        // 通过id查询
        if (mode == 1 || mode ==3 ) {
            try {
                Long userId = Long.valueOf(condition);
                user  = userMapper.queryUserById(userId);

            } catch (Exception e) {
                return new Result("请输入正确格式的用户id!");
            }
        } else if (mode == 2) {
            // 通过电话查询
            user = userMapper.queryUserByPhone(condition);
        }
        return new Result(true,Arrays.asList(user));
    }

    @Override
    public Result deleteUser(Long userId) {
        int level = userMapper.queryUserById(userId).getLevel();
        int level_ = UserHolder.getUser().getLevel();
        if (level_ <= level) {
            return new Result("权限不够,无法删除该用户!");
        }
        userMapper.deleteUserById(userId);
        userTasks.add(userId);
        log.info("用户:{} 删除用户成功",UserHolder.getUser().getUserId().toString());

        return new Result("删除成功!");
    }

    @Override
    public Result updateUser(User user) {
        int level = user.getLevel();
        int level_ = UserHolder.getUser().getLevel();
        if (level_ <= level) {
            return new Result("权限不够,无法修改该用户!");
        }
        userMapper.updateUser(user);
        log.info("用户:{} 修改修改用户信息成功",UserHolder.getUser().getUserId().toString());

        return new Result(true, "修改成功!");
    }

    @Override
    public Result countCategory() {
        int cloth = 0;
        int EE  = 0;
        int food = 0;
        int book = 0;
        int medicine = 0;
        int digitalProduct  = 0;
        Long userId = UserHolder.getUser().getUserId();
        List<GoodsDTO> goodsDTOS = goodsMapper.queryAllGoodsByUserId(userId);
        for (GoodsDTO goodsDTO : goodsDTOS) {
            switch (goodsDTO.getCategoryNameF()) {
                case "书籍":
                    book += 1;
                    break;
                case "医药":
                    medicine += 1;
                    break;

                case "数码":
                    digitalProduct += 1;
                    break;

                case "服装":
                    cloth += 1;
                    break;

                case "电器":
                    EE += 1;
                    break;
                case "食品":
                    food += 1;
                    break;
            }
        }
        List<Integer> categories = Arrays.asList(cloth, EE, food, book, medicine, digitalProduct);


        return new Result(true,categories);
    }

    @Override
    public Result countAppraise() {
        Long userId = UserHolder.getUser().getUserId();
        AppraiseDTO jicha = new AppraiseDTO();
        AppraiseDTO shiwang = new AppraiseDTO();
        AppraiseDTO yiban = new AppraiseDTO();
        AppraiseDTO mangyi = new AppraiseDTO();
        AppraiseDTO jinxi = new AppraiseDTO();
        jicha.setName("极差");
        shiwang.setName("失望");
        yiban.setName("一般");
        mangyi.setName("满意");
        jinxi.setName("惊喜");
        List<OrderDTO> orderDTOS = orderMapper.queryMySellOrders(userId);
        for (OrderDTO orderDTO : orderDTOS) {
            switch (orderDTO.getAppraise()) {
                case 1:
                    jicha.add();
                    break;
                case 2:
                    shiwang.add();
                    break;

                case 3:
                    yiban.add();
                    break;

                case 4:
                    mangyi.add();
                    break;

                case 5:
                     jinxi.add();
                    break;

            }
        }

        List<AppraiseDTO> appraiseDTOS = Arrays.asList(jicha, shiwang, yiban, mangyi, jinxi);

        return new Result(true,appraiseDTOS);
    }

    @Override
    public Result countDeals() {
        int M1 = 0;
        int M2 = 0;
        int M3 = 0;
        int M4 = 0;
        int M5 = 0;
        int M6 = 0;
        int M7 = 0;
        int M8 = 0;
        int M9 = 0;
        int M10 = 0;
        int M11 = 0;
        int M12 = 0;
        Long userId = UserHolder.getUser().getUserId();
        List<OrderDTO> orderDTOS = orderMapper.queryMySellOrders(userId);
        for (OrderDTO orderDTO : orderDTOS) {
            Date datetime = orderDTO.getDatetime();
            switch (getMonth(datetime)) {
                case 1:
                    M1 += 1;
                    break;
                case 2:
                    M2 += 1;
                    break;
                case 3:
                    M3 += 1;
                    break;
                case 4:
                    M4 += 1;
                    break;
                case 5:
                    M5 += 1;
                    break;
                case 6:
                    M6 += 1;
                    break;
                case 7:
                    M7 += 1;
                    break;
                case 8:
                    M8 += 1;
                    break;
                case 9:
                    M9 += 1;
                    break;
                case 10:
                    M10 += 1;
                    break;
                case 11:
                    M11 += 1;
                    break;
                case 12:
                    M12 += 1;
                    break;

            }
        }
        List<Integer> deals = Arrays.asList(M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12);

        return new Result(true,deals);
    }

    @Override
    public Result selectUsersByIds(List<Long> ids) {
        List<SimpleUseDTO> simpleUseDTOS = userMapper.selectUsersByIds(ids);
        return new Result(true, simpleUseDTOS);
    }

    // 查找用户(id)
    public User getById(Long id) {
        User user = userMapper.queryUserById(id);
        return user;
    }

    private Integer getMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int month = cal.get(Calendar.MONTH);

        return Integer.valueOf(month) + 1;
    }

}
